/**
 * <b>日期：</b>2015/04/02 2:35 PM<br/>
 * <b>Copyright (c)</b> 2015 广州天健软件有限公司<br/>
 */
package com.github.kennylee26.javaee.mvc;

import com.fasterxml.jackson.annotation.JsonView;
import com.github.kennylee26.javaee.mvc.entity.Role;
import com.github.kennylee26.javaee.mvc.entity.User;
import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * <b>类名称：</b>UserController<br/>
 * <b>类描述：</b>SpringMVC例子，都是返回JSON实体。<br />
 * <b>备注：</b> 更多更详细的见<a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-arguments">官方文档</a> <br/>
 *
 * @author kennylee <br />
 * @version 1.0.0 <br />
 */
@RestController
@Scope("prototype")
public class UserRestController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 通过URI传参。
     *
     * @param name String 用户名
     * @return User JSON实体
     */
    @RequestMapping(value = "/user/{name}", method = {RequestMethod.GET})
    public User getByUri(@PathVariable("name") String name) {
        logger.trace("getByUri, name is {}", name);
        User user = generateUser();
        user.setName(name);
        user.setComment("uri");
        return user;
    }

    /**
     * 通过URI传参，并限制header中的Accept值。
     *
     * @param name String 用户名
     * @return User JSON实体
     */
    @RequestMapping(value = "/user/{name}", produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.GET})
    public User getByUriWithProduces(@PathVariable("name") String name) {
        logger.trace("name is {}", name);
        User user = generateUser();
        user.setName(name);
        user.setComment("uri, ".concat(MediaType.APPLICATION_JSON_VALUE));
        return user;
    }

    /**
     * 通过request body传参，时间格式化。并用@JsonView控制返回的实体Bean的JSON字段。
     *
     * @param name String 用户名
     * @return User 去掉Password显示的JSON实体
     */
    @RequestMapping(value = "/user", method = {RequestMethod.GET})
    @JsonView(User.WithoutPasswordView.class)
    public User getByRequest(@RequestParam("name") String name, @RequestParam("time") @DateTimeFormat(pattern = "yyyy-MM-dd") Date createTime) {
        logger.trace("getByRequest, name is {}", name);
        User user = generateUser();
        user.setName(name);
        if (createTime != null) user.setCreateTime(createTime);
        user.setComment("requestBody");
        return user;
    }

    /**
     * 通过HttpServletRequest获取参数。
     *
     * @param request HttpServletRequest
     * @return User 去掉Password显示的JSON实体
     */
    @RequestMapping(value = "/user/request", method = {RequestMethod.GET})
    public User getByHttpRequest(HttpServletRequest request) {
        String name = request.getParameter("name");
        logger.trace("getByRequest, name is {}", name);
        User user = generateUser();
        user.setName(name);
        user.setComment("getByHttpRequest");
        return user;
    }

    /**
     * 通过request body传参。限制AJAX请求。
     *
     * @param name String 用户名
     * @return User
     */
    @RequestMapping(value = "/user/ajax", headers = "X-Requested-With=XMLHttpRequest", method = {RequestMethod.GET})
    public User getByRequestAndAjaxOnly(@RequestParam("name") String name) {
        logger.trace("getByRequestAndAjaxOnly, name is {}", name);
        User user = generateUser();
        user.setName(name);
        user.setComment("getByRequestAndAjaxOnly");
        return user;
    }

    /**
     * 通过request body传参，并把需要的值转换成Bean。
     *
     * @param user user
     * @return User
     */
    @RequestMapping(value = "/user/bean", method = {RequestMethod.GET})
    public User getFromRequertBean(User user) {
        logger.trace("getFromRequertBean, user is {}", user);
        user.setComment("getFromRequertBean");
        return user;
    }

    /**
     * 获取cookie里面的值
     *
     * @param name cookie中的name值
     * @return User
     */
    @RequestMapping(value = "/user/cookie", method = {RequestMethod.GET})
    public User getCookie(@CookieValue("name") String name) {
        logger.trace("getFromRequertBean, name is {}", name);
        User user = new User();
        user.setName(name);
        user.setComment("getCookie");
        return user;
    }

    /**
     * 获取header里面的值。
     *
     * @param acceptType header里面的Accept值。
     * @param name       header里面的name值。
     * @return
     */
    @RequestMapping(value = "/user/header", method = {RequestMethod.GET})
    public User getHeader(@RequestHeader("Accept") String acceptType, @RequestHeader("name") String name) {
        logger.trace("getHeader, name is {}, acceptType is {}", name, acceptType);
        User user = new User();
        user.setName(name);
        user.setComment("getHeader");
        return user;
    }


    /**
     * 附件上传简单例子。注意
     *
     * @param files 附件文件
     * @return User
     */
    @RequestMapping(value = "/user/file", method = {RequestMethod.POST})
    public User getFile(@RequestParam("file") MultipartFile[] files) throws IOException {
        logger.trace("getFile, file OriginalFilename is {}, size is {}", files[0].getOriginalFilename(), files[0].getSize());
        File saveAs = File.createTempFile("tmp", null);//另存到本地的文件
        long beforeSize = saveAs.length();
        FileUtils.copyInputStreamToFile(files[0].getInputStream(), saveAs);
        Assert.assertNotEquals(beforeSize, saveAs.length());
        User user = new User();
        user.setName(files[0].getOriginalFilename());
        user.setAvatarPath(saveAs.getAbsolutePath());
        user.setComment("getFile");
        return user;
    }

    /**
     * 附件上传例子。从request里面获取数据。注意附件上传时的request是 <code>MultipartHttpServletRequest</code>
     *
     * @param multipartRequest MultipartHttpServletRequest
     * @return User
     */
    @RequestMapping(value = "/user/file2", method = {RequestMethod.POST})
    public User getFileByRequest(MultipartHttpServletRequest multipartRequest) throws IOException {
        List<MultipartFile> files = multipartRequest.getFiles("file");
        String name = multipartRequest.getParameter("name");
        File saveAs = File.createTempFile("tmp", null);//另存到本地的文件
        long beforeSize = saveAs.length();
        FileUtils.copyInputStreamToFile(files.get(0).getInputStream(), saveAs);
        Assert.assertNotEquals(beforeSize, saveAs.length());
        logger.trace("getFile, file OriginalFilename is {}, size is {}", files.get(0).getOriginalFilename(), files.get(0).getSize());
        User user = new User();
        user.setComment(files.get(0).getOriginalFilename());
        user.setAvatarPath(saveAs.getAbsolutePath());
        user.setName(name);
        return user;
    }

    private User generateUser() {
        User user = new User();
        user.setPassword("111111");
        user.setDepartments(getDepartments());
        user.setRole(getRole());
        return user;
    }

    private List<String> getDepartments() {
        List<String> departments = Lists.newArrayList();
        departments.add("部门1");
        departments.add("部门2");
        departments.add("部门3");
        return departments;
    }

    private Role getRole() {
        Role role = new Role();
        role.setName("管理员");
        role.setPosition(10);
        return role;
    }

}
